﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using YanZhiwei.DotNet2.Utilities.Models;

namespace YanZhiwei.DotNet2.Utilities.WinForm
{
    /// <summary>
    ///Control帮助类
    /// </summary>
    public static class ControlHelper
    {
        #region 根据名称空间以及控件名称创建对应的控件
        /// <summary>
        /// 根据名称空间以及控件名称创建对应的控件
        /// </summary>
        /// <param name="ctrlName">控件名称</param>
        /// <param name="ctrlNamespace">控件名称空间</param>
        /// <returns>创建的控件</returns>
        public static Control CreateControl(string ctrlName, string ctrlNamespace)
        {
            try
            {
                Control _ctrl;
                switch (ctrlName)
                {
                    case "Label":
                        _ctrl = new Label();
                        break;
                    case "TextBox":
                        _ctrl = new TextBox();
                        break;
                    case "PictureBox":
                        _ctrl = new PictureBox();
                        break;
                    case "ListView":
                        _ctrl = new ListView();
                        break;
                    case "ComboBox":
                        _ctrl = new ComboBox();
                        break;
                    case "Button":
                        _ctrl = new Button();
                        break;
                    case "CheckBox":
                        _ctrl = new CheckBox();
                        break;
                    case "MonthCalender":
                        _ctrl = new MonthCalendar();
                        break;
                    case "DateTimePicker":
                        _ctrl = new DateTimePicker();
                        break;
                    default:
                        _ctrl = CreateWinFormControl(ctrlName, ctrlNamespace);
                        break;

                }
                return _ctrl;

            }
            catch (Exception)
            {
                return new Control();
            }
        }
        #endregion 
        #region 根据空间的名称空间以及控件名称创建控件
        /// <summary>
        /// 根据空间的名称空间以及控件名称创建控件
        /// </summary>
        /// <param name="ctrlName">控件名称</param>
        /// <param name="ctrlNamespace">控件名称空间</param>
        /// <returns>创建的控件</returns>
        public static Control CreateWinFormControl(string ctrlName, string ctrlNamespace)
        {
            Assembly _controlAsm = Assembly.Load(ctrlNamespace);
            Type _controlType = _controlAsm.GetType(ctrlNamespace + "." + ctrlName);
            return (Control)Activator.CreateInstance(_controlType);
        }
        #endregion 
        #region 设置控件属性值
        /// <summary>
        /// 设置控件属性值
        /// </summary>
        /// <param name="ctrl">控件</param>
        /// <param name="ctrlPropertyList">包含空间属性和属性值的Hashtable</param>
        public static void SetProperties(this Control ctrl, Hashtable ctrlPropertyList)
        {
            if (ctrl != null && ctrlPropertyList != null)
            {
                PropertyDescriptorCollection _properties = TypeDescriptor.GetProperties(ctrl);
                foreach (PropertyDescriptor property in _properties)
                {
                    if (ctrlPropertyList.Contains(property.Name))
                    {
                        Object _obj = ctrlPropertyList[property.Name];
                        try
                        {
                            property.SetValue(ctrl, _obj);
                        }
                        catch (Exception)
                        {
                        }
                    }
                }
            }
        }
        #endregion 
        #region 克隆控件
        /// <summary>
        /// 克隆控件
        /// </summary>
        /// <param name="ctrl">需要克隆的控件</param>
        /// <returns>返回克隆的控件</returns>
        public static Control Clone(this Control ctrl)
        {
            ClipboardCtrl _clipboardCtrl = new ClipboardCtrl(ctrl);
            Control _control = CreateControl(_clipboardCtrl.CtrlName, _clipboardCtrl.CtrlNamespace);
            _control.SetProperties(_clipboardCtrl.CtrlPropertyList);
            return _control;
        }
        #endregion 
        #region 同类别的控件克隆
        /// <summary>
        /// 同类别的控件克隆
        /// </summary>
        /// <typeparam name="T">空间类型</typeparam>
        public static Control CloneTo<T>(this T t, T u) where T : Control
        {
            ClipboardCtrl _clipboardCtrl = new ClipboardCtrl(t);
            Rectangle _rectanle = u.Bounds;
            u.SetProperties(_clipboardCtrl.CtrlPropertyList);
            u.SetBounds(_rectanle.X, _rectanle.Y, _rectanle.Width, _rectanle.Height);
            return u;
        }
        #endregion 
        #region 将控件复制到放在剪贴板上
        /// <summary>
        /// 将控件复制到放在剪贴板上
        /// </summary>
        /// <param name="ctrl">需要复制的控件</param>
        public static void CopyToClipBoard(this Control ctrl)
        {
            ClipboardCtrl _clipboardCtrl = new ClipboardCtrl(ctrl);
            IDataObject _dObject = new DataObject();
            _dObject.SetData(ClipboardCtrl.Format.Name, true, _clipboardCtrl);
            Clipboard.SetDataObject(_dObject, false);
        }
        #endregion 
        #region 从剪切板获取控件
        /// <summary>
        /// 从剪切板获取控件
        /// </summary>
        /// <returns>Control</returns>
        public static Control GetCtrlFromClipBoard()
        {
            Control _ctrl = new Control();
            IDataObject _dObject = Clipboard.GetDataObject();
            if (_dObject.GetDataPresent(ClipboardCtrl.Format.Name))
            {
                ClipboardCtrl _clipboardCtrl = _dObject.GetData(ClipboardCtrl.Format.Name) as ClipboardCtrl;
                _ctrl = CreateControl(_clipboardCtrl.CtrlName, _clipboardCtrl.CtrlNamespace);
                SetProperties(_ctrl, _clipboardCtrl.CtrlPropertyList);
            }
            return _ctrl;
        }
        #endregion
        #region 移除控件某个事件
        /// <summary>
        /// 移除控件某个事件
        /// </summary>
        /// <param name="control">控件</param>
        /// <param name="eventName">需要移除的控件名称eg:EventClick</param>
        public static void RemoveEvent(this Control control, string eventName)
        {
            FieldInfo _fl = typeof(Control).GetField(eventName, BindingFlags.Static | BindingFlags.NonPublic);
            if (_fl != null)
            {
                object _obj = _fl.GetValue(control);
                PropertyInfo _pi = control.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
                EventHandlerList _eventlist = (EventHandlerList)_pi.GetValue(control, null);
                if (_obj != null && _eventlist != null)
                    _eventlist.RemoveHandler(_obj, _eventlist[_obj]);
            }
        }
        #endregion 
        #region  按名称查找控件
        /// <summary>
        /// 按名称查找控件
        /// </summary>
        /// <param name="parentControl">查找控件的父容器控件</param>
        /// <param name="findCtrlName">查找控件名称</param>
        /// <returns>若没有查找到返回NULL</returns>
        public static Control FindControl(this Control parentControl, string findCtrlName)
        {
            Control _findedControl = null;
            if (!string.IsNullOrEmpty(findCtrlName) && parentControl != null)
            {
                foreach (Control ctrl in parentControl.Controls)
                {
                    if (ctrl.Name.Equals(findCtrlName))
                    {
                        _findedControl = ctrl;
                        break;
                    }
                }
            }
            return _findedControl;
        }
        #endregion 
        #region 向下递归查找控件
        /// <summary>
        /// 向下递归查找控件
        /// </summary>
        /// <param name="parentControl">查找控件的父容器控件</param>
        /// <param name="findCtrlName">查找控件名称</param>
        /// <returns>若没有查找到返回NULL</returns>
        public static Control DownRecursiveFindControl(this Control parentControl, string findCtrlName)
        {
            Control _findedControl = null;
            if (!string.IsNullOrEmpty(findCtrlName) && parentControl != null)
            {
                foreach (Control ctrl in parentControl.Controls)
                {
                    if (ctrl.Name.Equals(findCtrlName))
                    {
                        _findedControl = ctrl;
                        break;
                    }
                    else
                    {
                        if (ctrl.Controls.Count > 0)
                            _findedControl = DownRecursiveFindControl(ctrl, findCtrlName);
                    }
                }
            }
            return _findedControl;
        }
        #endregion 
        #region 将Control转换某种控件类型
        /// <summary>
        /// 将Control转换某种控件类型
        /// </summary>
        /// <typeparam name="T">控件类型</typeparam>
        /// <param name="control">Control</param>
        /// <param name="result">转换结果</param>
        /// <returns>若成功则返回控件；若失败则返回NULL</returns>
        public static T Cast<T>(this Control control, out bool result) where T : Control
        {
            result = false;
            T _castCtrl = null;
            if (control != null)
            {
                if (control is T)
                {
                    try
                    {
                        _castCtrl = control as T;
                        result = true;
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(string.Format("将Control转换某种控件类型异常，原因:{0}", ex.Message));
                        result = false;
                    }
                }
            }
            return _castCtrl;
        }
        #endregion 
        #region 向容器控件中添加控件
        /// <summary>
        /// 向容器控件中添加控件
        /// </summary>
        /// <typeparam name="C">泛型</typeparam>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="c">容器控件</param>
        /// <param name="t">添加控件</param>
        public static void AddControl<C, T>(this C c, T t)
            where T : Control, new()
            where C : Control
        {
            if (t == null)
                t = new T();
            t.Dock = DockStyle.Fill;
            c.Controls.Clear();
            c.Controls.Add(t);
        }
        #endregion 
        #region 设置控件Text【线程安全】
        /// <summary>
        /// 设置控件Text【线程安全】
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="t">控件</param>
        /// <param name="txt">Text</param>
        public static void SetTextTF<T>(this T t, string txt) where T : Control
        {
            t.UIThread((MethodInvoker)delegate
            {
                t.Text = txt;
            });
        }
        #endregion 
        #region  设置控件Enabled【线程安全】
        /// <summary>
        /// 设置控件Enabled【线程安全】
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="t">控件</param>
        /// <param name="enable">Enabled</param>
        public static void SetEnableTF<T>(this T t, bool enable) where T : Control
        {
            t.UIThread((MethodInvoker)delegate
            {
                t.Enabled = enable;
            });
        }
        #endregion 
        #region 设置控件的Tag属性【线程安全】
        /// <summary>
        /// 设置控件的Tag属性【线程安全】
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="t">控件</param>
        /// <param name="tag">Tag</param>
        public static void SetTagTF<T>(this T t, object tag) where T : Control
        {
            t.UIThread((MethodInvoker)delegate
            {
                t.Tag = tag;
            });
        }
        #endregion 
        #region 设置控件的Tag,Text属性【线程安全】
        /// <summary>
        /// 设置控件的Tag,Text属性【线程安全】
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="t">控件</param>
        /// <param name="tag">Tag</param>
        /// <param name="txt">Text</param>
        public static void SetTextTagTF<T>(this T t, object tag, string txt) where T : Control
        {
            t.UIThread((MethodInvoker)delegate
            {
                t.Tag = tag;
                t.Text = txt;
            });
        }
        #endregion 
        #region 设置控件的Enabled，Text属性【线程安全】
        /// <summary>
        /// 设置控件的Enabled，Text属性【线程安全】
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="t">控件</param>
        /// <param name="enable">Enabled</param>
        /// <param name="txt">Text</param>
        public static void SetEnableTextTF<T>(this T t, bool enable, string txt) where T : Control
        {
            t.UIThread((MethodInvoker)delegate
            {
                t.Enabled = enable;
                t.Text = txt;
            });
        }
        #endregion 
        #region 设置控件的Visible属性【线程安全
        /// <summary>
        /// 设置控件的Visible属性【线程安全】
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="t">控件</param>
        /// <param name="visible">Visible</param>
        public static void SetVisibleTF<T>(this T t, bool visible) where T : Control
        {
            t.UIThread((MethodInvoker)delegate
            {
                t.Visible = visible;
            });
        }
        #endregion 
        #region 获取控件的Tag属性【线程安全】
        /// <summary>
        /// 获取控件的Tag属性【线程安全】
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="t">控件</param>
        /// <returns>object</returns>
        public static object GetTagTF<T>(this T t) where T : Control
        {
            object _tag = null;
            t.UIThread((MethodInvoker)delegate
            {
                _tag = t.Tag;
            });
            return _tag;
        }
        #endregion 
    }
}
